<?php
/**
 * Created by PhpStorm.
 * User: Zhoujinda
 * Date: 2016/3/15
 * Time: 19:38
 */

namespace Api\Domain;

use Admin\Api\OrdersPaycodeApi;
use Shop\Api\AddressApi;
use Shop\Api\MemberConfigApi;
use Shop\Api\OrdersApi;
use Shop\Api\OrdersItemApi;
use Shop\Api\RedEnvelopeApi;
use Shop\Api\RedEnvelopeTplApi;
use Shop\Api\ShoppingCartApi;
use Shop\Api\StorePromotionApi;
use Shop\Model\OrdersModel;
use Shop\Api\ProductSkuApi;
use Shop\Api\OrdersInfoViewApi;
use Shop\Api\OrderStatusApi;
use Shop\Api\OrderRefundApi;
use Shop\Api\OrdersExpressApi;

class OrdersDomain extends BaseDomain{


    protected $business_code = "orders";

    protected $allowType = array("json", "rss", "html");

    /**
     * 订单添加
     * UID,idcode(别人的),cartids 购物车里的商品id
     * from,note,cartids,
     * addr_id 收货地址ID
     */
    public function add(){
        if(IS_POST){
            $this->checkVersion(100);
            addLog("Orders/add",$_GET,$_POST,"应用" . $this->client_id . "调用订单添加接口");
            //购买人的用户ID
            $uid = $this->_post("uid",0,"缺少用户ID");
            $idcode = $this->_post("idcode",""); //优惠码
            $cart_ids = $this->_post("cart_ids","","购物车信息缺失");
            $address_id = $this->_post("address_id","","缺失收货地址"); //收货地址ID
            $note = $this->_post("note","");
            $from = $this->_post("from",""); //订单来源
            $pay_type = 1; //支付类型 1:支付宝

            //1. 收货地址
            if(empty($address_id)){
                $this->apiReturnErr('收货地址缺失');
            }
            $result = apiCall(AddressApi::GET_INFO,array(array('id'=>$address_id)));
            $this->checkApiCallResult($result,true,'收货地址缺失');

            $address = $result['info'];
            unset($address['id']);

            $entity = array();

            //合并收货地址
            $entity = array_merge($entity,$address);

            //2. 购物车信息
            $map = array(
                'uid'=>$uid,
                'id'=>array('in',$cart_ids),
            );

            $result = apiCall(ShoppingCartApi::QUERY_WITH_STORE_INFO,array($map));

            $this->checkApiCallResult($result,true,"购物车里没有商品哦!");
            $cart = $result['info'];

            $cart = $this->groupByStore($cart);

            //1. 本商城生成的支付编号
            $payCode = "";
            $total_price = 0;
            //3. 对每个店铺生成一张订单
            foreach($cart as $key=>$vo){


                //$this->apiReturnErr($vo);
                //1. 备注
                $entity['note'] = $note;
                $entity['uid'] = $uid;
                $entity['order_code'] = getOrderid($uid);
                $entity['storeid'] = $key;
                $entity['idcode'] = $idcode;
                $entity['from'] = $from;
                $entity['pay_type'] = $pay_type;
                $post_price = 0;
                $discount_money = 0;
                $free_shipping = 0; //是否包邮

                $calInfo = $this->calPrice($address,$vo);

                //计算运费
                foreach($vo as $v_carts){
                    $post_price = $post_price + $this->getPostPrice($v_carts['id'],$address_id,$uid);
                }

                //使用优惠码
                    //1.红包
                if(!empty($idcode)){
                    addLog("Api/Orders/Add" ,"","红包ID:".$idcode,"[调试使用红包]", true);
                    $discount_money = $this->useRedEnvelope($idcode,$uid,$calInfo['price']);
                    //$entity['discount_money'] = $this->useRedEnvelope($idcode,$uid,$entity['price']);
                }

                   //2.店铺优惠
                $result = apiCall(StorePromotionApi::GET_INFO,array(array('store_id'=>$key)));


                if(!$result['status']){
                    addLog("Api/Orders/Add" , $entity , $result['info'] , '[查询店铺优惠失败]' , true);
                    $this->apiReturnErr('订单添加失败');
                }else{
                    if(!is_null($result['info'])){
                        $Promotion = $result['info'];
                        $now_time = time();
                        if($Promotion['start_time']<= $now_time && $now_time <=$Promotion['end_time']){//在活动期内
                            if($Promotion['condition'] <= $calInfo['price']){

                                $discount_money += $Promotion['discount_money'];//满减优惠
                                $free_shipping = $Promotion['free_shipping'];

                            }

                        }
                    }
                }

                //计算优惠后价格+运费
                $calInfo['post_price'] = $free_shipping?0:$post_price;
                $calInfo['discount_money'] = $discount_money;
                $calInfo['price'] -= $discount_money;

                if($calInfo['price'] < 0){
                    $calInfo['price'] = 0;
                }
                $calInfo['price'] = $calInfo['price'] + $calInfo['post_price'];

                $entity = array_merge($entity,$calInfo);


                addLog("Api/Orders/Add" , $entity , $address , '[订单添加对象]' , true);
                $result = apiCall(OrdersApi::ADD_ORDER,array($entity));

                if($result['status']){

                    $payCode .= $result['info'].";";
                    $total_price = $total_price + $entity['price'];

                }

            }

            //4. 添加到订单之后，就该删除购物车的数据
            $this->deleteFromShoppingCart($uid,$cart_ids);
            $now = time();
            //5. 返回支付编号,用这个支付编号来生成支付信息
            $ordersPayCode = array(
                'order_content'=>$payCode,
                'create_time'=>$now,
                'pay_type'=>$pay_type,
                'pay_money'=>$total_price,
                'uid'=>$uid,
            );

            $result = apiCall(OrdersPaycodeApi::ADD,array($ordersPayCode));
            if($result['status']){
                $pay_id = $result['info'];

                $info = $this->getPayReturnInfo($pay_id,$uid,$total_price);

                $this->apiReturnSuc($info);
            }else{
                $this->apiReturnErr("支付信息生成失败!");
            }


        }else{
            $this->apiReturnErr('只支持post请求');
        }

    }

    /**
     * 查询订单详情
     */
    public function detail(){
        if(IS_POST){
            $this->checkVersion(100);
            addLog("Orders/detail",$_GET,$_POST,"应用" . $this->client_id . "调用查询订单详情接口");
            $id=$this->_post('id','','缺少订单ID'); //订单ID

            $map=array(
                'id'=>$id,
            );
            $result=apiCall(OrdersInfoViewApi::GET_INFO,array($map));




            if($result['status']){

                $order=$result['info'];

                if(is_null($order)){
                    $this->apiReturnErr("获取失败,没有此订单!");
                }

                $order['store_logo_url'] = getImageUrl($order['store_logo']);

                $map=array(
                    'order_code'=>$order['order_code'],
                );
                $result=apiCall(OrdersItemApi::QUERY_NO_PAGING,array($map));
                if($result['status']){
                    $order['items'] = $result['info'];

                    $order['items'] = $this->convertDetail($result['info']);

                }else {
                    $this->apiReturnErr("查询中发生错误，请联系相关人员");
                }

                $this->apiReturnSuc($order);
            }else{
                $this->apiReturnErr("查询中发生错误，请联系相关人员");
            }
        }else{
            $this->apiReturnErr('只支持post请求');
        }

    }

    public function pay(){
        if(IS_POST){
            $this->checkVersion(100);
            addLog("Orders/pay",$_GET,$_POST,"应用" . $this->client_id . "调用订单支付接口");

            $uid = $this->_post("uid","","缺少用户ID");
            $order_id = $this->_post("order_id","","缺少订单ID");
            $pay_type = 0;

            $map = array(
                'id'=>$order_id,
                'uid'=>$uid,
            );

            $result = apiCall(OrdersApi::GET_INFO,array($map));

            if(!$result['status']){
                LogRecord($result['info'],__FILE__.__LINE__);
                $this->apiReturnErr($result['info']);
            }

            if(is_null($result['info'])){
                $this->apiReturnErr("订单ID非法!");
            }

            $order = $result['info'];

            $pay_code = $order['order_code'].';';

            $now  = time();
            $total_price = $order['price'];

            //5. 返回支付编号,用这个支付编号来生成支付信息
            $ordersPayCode = array(
                'order_content'=>$pay_code,
                'create_time'=>$now,
                'pay_type'=>$pay_type,
                'pay_money'=>$total_price,
                'uid'=>$uid,
            );

            $result = apiCall(OrdersPaycodeApi::ADD,array($ordersPayCode));
            if($result['status']){
                $pay_id = $result['info'];

                $info = $this->getPayReturnInfo($pay_id,$uid,$total_price);

                $this->apiReturnSuc($info);
            }else{
                $this->apiReturnErr("支付信息生成失败!");
            }
        }else{
            $this->apiReturnErr('只支持post请求');
        }

    }


    /**
     * 订单取消
     */
    public function qxorder(){
        if(IS_POST){
            $this->checkVersion(100);
            addLog("Orders/qxorder",$_GET,$_POST,"应用" . $this->client_id . "调用订单取消接口");
            //首先接收用户ID，
            $uid=$this->_post("uid",0,'用户ID缺失');

            $order_code=$this->_post('order_code',0,'订单编号缺失');

            $result = apiCall(OrderStatusApi::CANCEL,array($order_code,false,$uid));

            if($result['status']){
                $this->apiReturnSuc('取消成功!');
            }else{
                $this->apiReturnErr('取消失败!');
            }
        }else{
            $this->apiReturnErr('只支持post请求');
        }

    }

    /**
     * 订单确认收货
     */
    public function sureorder(){
        if(IS_POST){
            $this->checkVersion(100);
            addLog("Orders/sureorder",$_GET,$_POST,"应用" . $this->client_id . "调用订单确认收货接口");
            //首先接收用户ID，
            $uid=$this->_post("uid",0,'用户ID缺失');

            $order_code=$this->_post('order_code',0,'订单编号缺失');

            $result = apiCall(OrderStatusApi::CONFIRM_RECEIVE,array($order_code,false,$uid));

            if($result['status']){
                $this->apiReturnSuc('成功确认收货!');
            }else{
                $this->apiReturnErr('确认收货失败!'.$result['info']);
            }
        }else{
            $this->apiReturnErr('只支持post请求');
        }

    }



    /**
     * 申请售后
     */
    public function afterSale(){
        if(IS_POST){
            $this->checkVersion(100);
            addLog("Orders/afterSale",$_GET,$_POST,"应用" . $this->client_id . "调用订单申请售后接口");
            $uid = $this->_post("uid",0,"缺少用户ID");

            $order_code = $this->_post('order_code','',"无法获取订单!");

            $text=$this->_post('reason','无');

            //
            $map = array(
                'order_code'=>$order_code
            );
            $result = apiCall(OrderRefundApi::GET_INFO,array($map));
            if($result['status']){
                $refund_info = $result['info'];
            }else{
                $this->apiReturnErr('申请售后失败!');
            }

            $entity = array('create_time'=>time(),'reason'=>$text,'valid_status'=>0,'reply_msg'=>'','order_code'=>$order_code);
            if(is_null($refund_info)){
                $result = apiCall(OrderRefundApi::ADD,array($entity));
            }else{

                if($refund_info['valid_status']==0){
                    //待审核，无法再次申请售后，直接返回提示文字（正在审核中）
                    $this->apiReturnSuc('您已经申请过售后，请耐心等待客服处理！');
                }else{
                    //重新发起售后
                    $result = apiCall(OrderRefundApi::SAVE,array($map,$entity));
                }
            }

            if(!$result['status']){
                $this->apiReturnErr('申请售后失败!');
            }

            //修改订单的售后状态

            $result = apiCall(OrderRefundApi::CHANGE_SERVICE_STATUS,array($order_code,OrdersModel::CS_PENDING));
            if($result['status']){
                $this->apiReturnSuc('申请售后成功，等待客服反馈!');
            }else{
                $this->apiReturnErr('订单发生未知错误!');
            }

        }else{
            $this->apiReturnErr('只支持post请求');
        }

    }


    /**
     * 获取订单物流信息
     */
    public function express(){
        if(IS_POST){
            $this->checkVersion(100);
            addLog("Orders/express",$_GET,$_POST,"应用" . $this->client_id . "调用获取订单物流信息接口");
            $order_code = $this->_post("order_code","","订单编号缺失!");

            $result = apiCall(OrdersExpressApi::GET_INFO,array(array('order_code'=>$order_code)));
            $this->checkApiCallResult($result,false,"发货信息获取失败!");

            $this->apiReturnSuc($result['info']);
        }else{
            $this->apiReturnErr('只支持post请求');
        }

    }




    /**
     * 订单分页查询
     */
    public function query(){

        if(IS_POST){
            $this->checkVersion(100);
            addLog("Orders/query",$_GET,$_POST,"应用" . $this->client_id . "调用订单分页查询接口");

            $uid = $this->_post('uid','','用户ID缺失');
            $curpage = $this->_post('curpage',1);
            $pagesize = $this->_post('pagesize',10);
            $status = $this->_post('status','','状态缺失');

            $curpage = intval($curpage);
            $pagesize = intval($pagesize);

            if($curpage < 1){
                $curpage = 1;
            }
            if($pagesize > 30){
                $pagesize = 30;
            }
            if($pagesize <= 0){
                $pagesize = 10;
            }

            $map=array(
                'uid'=>$uid,
            );

            if(!empty($status)){
                $map = array_merge($map,$this->getQueryStatus($status));
            }

            $page = array(
                'curpage'=>$curpage,
                'size'=>$pagesize
            );

            $order = "updatetime desc";

            $result = apiCall(OrdersApi::QUERY,array($map,$page,$order));
            if($result['status']){
                $orderList = $result['info']['list'];
                if(is_null($orderList)){
                    $this->apiReturnSuc('');
                }

            }else{
                addLog('Orders/query',$_GET,$_POST,$result['info'],true);
                $this->apiReturnErr('查询失败');
            }

            //查询orders_item
            $mapItem = $this->getMapFromResult($orderList);

            $result = apiCall(OrdersItemApi::QUERY_NO_PAGING,array($mapItem));

            if($result['status']){
                $list =  $this->combine($orderList,$result['info']);
                $return = array('list'=>$list);
                $return['curpage'] = $curpage;
                $return['pagesize'] = $pagesize;
                $this->apiReturnSuc($return);
            }else{
                addLog('Orders/query',$_GET,$_POST,$result['info'],true);
                $this->apiReturnErr('查询失败');
            }


        }else{
            $this->apiReturnErr('只支持post请求');
        }



    }

    /**
     * 将此处查询状态
     * 转换为订单状态或支付状态
     * @param $status
     * @return array
     */
    private function getQueryStatus($status){
        /*
            status = 0 //全部状态,

            status = 1 //待付款

            status = 2 //待发货

            status = 3 //待收货

            status = 4 //已收货

            status = 5 //退款/售后
            */

        $map = array();
        switch($status){
            case 0:
                break;
            case 1:
                $map['pay_status'] = OrdersModel::ORDER_TOBE_PAID;
                $map['order_status'] = OrdersModel::ORDER_TOBE_CONFIRMED;
                break;
            case 2:
                $map['pay_status'] = OrdersModel::ORDER_PAID;
                $map['order_status'] = array('in',array(OrdersModel::ORDER_TOBE_SHIPPED,OrdersModel::ORDER_TOBE_CONFIRMED));
                break;
            case 3:

                $map['order_status'] = OrdersModel::ORDER_SHIPPED;
                break;
            case 4:
                $map['order_status'] = OrdersModel::ORDER_RECEIPT_OF_GOODS;
                break;
            case 5:
                $map['cs_status'] = array('in',array(OrdersModel::CS_PENDING,OrdersModel::CS_PROCESSED));
                break;
            default:
                break;
        }
        return $map;
    }

    /**
     * Convert
     * @param $order_list
     * @return mixed
     */
    private function combine($orderList,$itemList){
        foreach($itemList as $vo){
            $order = &$orderList[$vo['order_code']];
            $vo['img_url'] = getImageUrl($vo['img']);
            unset($vo['img']);
            if(!empty($order)){
                array_push($order['_items'],$vo);
            }
        }

        return $orderList;
    }

    private function getMapFromResult(&$list){

        $newList = array();

        $mapItem = array();

        foreach($list as $vo){
            array_push($mapItem,$vo['order_code']);
            $newList[$vo['order_code']] = $vo;
            $newList[$vo['order_code']]['_items'] = array();
        }
        $list = $newList;
        return array('order_code'=>array('in',$mapItem));
    }

    /**
     *
     * @param $result
     * @param bool $cantBeNull
     * @param string $whenNullMsg 当为空时的信息
     */
    protected function checkApiCallResult($result,$cantBeNull=true,$whenNullMsg="获取信息为空!"){

        if(!$result['status']){
            $this->apiReturnErr($result['info']);
        }

        if($cantBeNull && is_null($result['info'])){
            $this->apiReturnErr($whenNullMsg);
        }

    }

    //对商品信息进行分组
    private function groupByStore($cart){
        $new_cart = array();

        foreach($cart as $vo){
            $store_id = $vo['store_id'];
            if(!isset($new_cart[$store_id])){
                $new_cart[$store_id] = array();
            }
            array_push($new_cart[$store_id],$vo);
        }
        return $new_cart;
    }

    /**
     * 计算单个订单里的金额
     * @param $address array 收货地址，计算运费用
     * @param $items   array  购物的商品信息，购物车项
     * @param $selfCoupon  array 自己的优惠信息
     * @param $otherCoupon array  其它人的优惠信息，自己可以用，填了优惠码,也可空
     * @return array
     */
    private function calPrice($address,$items){
        $entity = array();
        $entity['count'] = 0;       //总件数
        $entity['price'] = 0;       //应付金额
        $entity['post_price'] = 0; //运费
        $entity['discount_money'] = 0; //折扣金额数
        $entity['brokerage_ratio'] = 0; //返佣比例
        $entity['tax_amount'] = 0; //税款
        $entity['goods_amount'] = 0; //货款＝商品金额＊数量 总和
        $entity['items']  = array();

        foreach($items as $item){
            //检查购物车中商品最新信息
            $result = apiCall(ProductSkuApi::GET_INFO,array(array('id'=>$item['psku_id'])));
            if($result['status']){
                if(is_null($result['info'])){
                    addLog('Orders/calPrice',$item,'购物车ID：'.$item['id'].'商品无效','调试',true);
                    $this->apiReturnErr('购物车ID：'.$item['id'].'商品无效');
                }else{
                    $sku = $result['info'];
                    //判断购物车价格是否最新
                    if($item['price']!=$sku['price']){
                        $this->apiReturnErr('购物车ID：'.$item['id'].'商品价格需要更新');
                    }
                    if($sku['quantity']<$item['count']){
                        $this->apiReturnErr('购物车ID：'.$item['id'].'商品库存不足');
                    }
                    //更新商品信息
                }
            }else{
                $this->apiReturnErr('购物车ID：'.$item['id'].'p_skuid查询失败');
            }

            $post_price = 0;
            $taxAmount =0;

            $cnt = intval($item['count']);
            //TODO:1. 该商品折扣价格
            $discount_price = 0;

            //TODO:2. 该商品使用优惠码之后的价格

            //4. 货款
            $goodsAmount = $cnt * $item['price'];

            //5.应付金额
            $price =  $cnt * ($item['price'] - $discount_price) + $post_price;

            if($price < 0 ){
                LogRecord("商品优惠金额不能为负!",__FILE__.__LINE__);
                $this->apiReturnErr("服务器计算商品价格出错!");
            }

            //1. 优惠金额
            $entity['discount_money'] = $entity['discount_money'] + $cnt*$discount_price;//折扣
            $entity['tax_amount'] = $entity['tax_amount'] + $taxAmount; //税款
            $entity['goods_amount'] = $entity['goods_amount'] + $goodsAmount; //货款
            $entity['post_price'] = $post_price; //运费
            $entity['price'] = $entity['price'] + $price;

            array_push($entity['items'],$item);


        }

        addLog("CalDiscountMoney 计算的应付金额，不含运费",$entity,"","[调试]",true);
        return $entity;
    }

    /**
     * 订单使用红包(优惠码)
     */
    private function useRedEnvelope($idcode,$uid,$price){

        $result = apiCall(RedEnvelopeApi::GET_INFO,array(array('id'=>$idcode,'uid'=>$uid,'use_status'=>0)));
        if($result['status']){

            if(is_null($result['info'])){
                //没有可使用的红包
                addLog('Orders/useRedEnvelope','idcode='.$idcode.' uid='.$uid,'没有可使用的红包','调试',true);
                return 0;
            }else{
                $RedEnvelope = $result['info'];
                //检查红包是否过期
                $endDate = $RedEnvelope['get_time'] + $RedEnvelope['expire_time'];
                if($endDate < time()){
                    //红包已过期无法使用
                    addLog('Orders/useRedEnvelope','idcode='.$idcode.' uid='.$uid,'红包已过期无法使用','调试',true);
                    return 0;
                }

                //使用该红包
                //1.判断红包条件
                $result = apiCall(RedEnvelopeTplApi::GET_INFO,array(array('id'=>$RedEnvelope['tpl_id'])));
                if($result['status']){
                    if(is_null($result['info'])){
                        //没有红包模版
                        addLog('Orders/useRedEnvelope','idcode='.$idcode.' uid='.$uid,'没有红包模版','调试',true);
                    }else{
                        $RedEnvelopeTpl = $result['info'];

                        if($RedEnvelopeTpl['use_condition']<=$price){
                            //满足红包使用条件
                            //1.使用红包
                            $result = apiCall(RedEnvelopeApi::SAVE_BY_ID,array($idcode,array('use_status'=>1)));
                            if($result['status']){
                                //使用成功
                                addLog('Orders/useRedEnvelope','idcode='.$idcode.' uid='.$uid,'使用成功','调试'.$RedEnvelope['money'],true);
                                return $RedEnvelope['money'];

                            }else{
                                $this->apiReturnErr('使用优惠码失败');
                            }
                        }else{
                            return 0;
                        }
                    }
                }else{
                    $this->apiReturnErr('获取优惠码模版失败');
                }



            }

        }else{
            addLog('Orders/useRedEnvelope','idcode='.$idcode.' uid='.$uid,$result,'调试',true);
            $this->apiReturnErr('获取优惠码信息失败');
        }
        return 0;

    }

    /**
     * 从购物车中删除
     * @author 老胖子-何必都 <hebiduhebi@126.com>
     * @param $uid
     * @param $cart_ids
     */
    private function deleteFromShoppingCart($uid,$cart_ids){
        $map = array(
            'uid'=>$uid,
            'id'=>array('in',$cart_ids),
        );

        $result = apiCall(ShoppingCartApi::DELETE,array($map));
        if(!$result['status']){
            LogRecord($result['info'],__FILE__.__LINE__);
        }
    }

    private function getPayReturnInfo($pay_id,$uid,$total_price){
        $now = time();

        $code = 'T'.$now.'U'.$uid.'P'.$pay_id;
        $name = '订单'.$code;
        $desc = $name;
        //保留2位
        $total_price = round($total_price,2);
        $info = array(
            'code'=>$code,
            'name'=>$name,
            'desc'=>$desc,
            //@author 老胖子-何必都 <hebiduhebi@126.com>
            //转换成字符串，否则IOS端解析成数字类型时精度会有问题，比如74.10 被解析成74.09999999999999,从而导致APP端验证失败!
            'total_price'=>strval($total_price)
        );

        $encode = urlencode($code.$name.$desc.$total_price);
        $encode = md5(strtolower($encode));

        $info['key'] = pay_encrypt_md5($encode);
        $info['show_url'] = C('SITE_URL');

        return $info;
    }

    /**
     * Convert
     * @param $order_list
     * @return mixed
     */
    private function convertDetail($list){
        foreach($list as &$vo) {
            $vo['img_url'] = getImageUrl($vo['img']);
        }
        return $list;
    }

    /**
     * 获取运费金额
     */
    private function getPostPrice($cart_id,$address_id,$uid){
        $result = apiCall('Api/Freight/calc',array($cart_id,$address_id,$uid),'Domain');
        if($result['status']){
            return $result['info'];
        }else{
            $this->apiReturnErr('运费计算失败');
        }
        return 0;
    }


}